package test.thread;

import java.util.ArrayList;
import java.util.List;

/**
 * 用 join 方式同步（其实不太好，不如用 SynClass2 的方式）
 * 
 * @author  姓名:along 工号
 * @version  [版本号, 2017年8月2日]
 * @see  [相关类/方法]
 * @since  [产品/模块版本]
 */
class SynClass3 implements Runnable{
    
    private static Integer count = 0;
    private int id = count++;
    
    private void printState(String s){
    	synchronized(count){ // 这个输出不能被打断
    		System.out.println(s+" id: "+id+" "+"State: "+Thread.currentThread().getState().name());
            int id=0;
            for(Thread t: tList){
                System.out.println("id: "+id+" "+"State: "+t.getState().name());
                ++id;
            }
    	}
    }
    
    private void StaticJoin(){
        try {
            tList.get(0).join();
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    private void StaticSleep(long t){
    	try {
			Thread.sleep(t);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
    }
    
    private List<Thread> tList = null;
    
    public SynClass3(List<Thread> tList) {
		super();
		this.tList = tList;
	}
    
    private void startOthersThread(){
    	printState("启动其它线程前");
    	synchronized(count){
			int i=0;
			for(Thread t: tList){
				if( i++>0 )
					t.start();
			}
		}
    	printState("启动其它线程后");
    }

	private void fun(){
	    
        if( 0!=id ){   // 不是第一个线程则等待
            // 实际上这里执行完不一定马上会执行StaticJoin（可能会被其它线程“插队”）
            // 因此如果前后锁的对象正好是 join 的对象时，不应该用 join 而用 wait .
            // 除非 join 的对象与前后锁不同时，才可以这样用
            printState("主动 join前");
            StaticJoin();   // 主动 wait
            printState("主动 join后");
        }
	    
	    if( 0==id ){
            startOthersThread();
            
            StaticSleep(128);
        }
    		
    	synchronized(count){
	        printState("进同步块后");
	        StaticSleep(128);
	        printState("出同步块前");
		}
		
		printState("出同步块后");
    }

    @Override
    public void run() {
        fun();
    }
}

public class BlockTest2 {
    
    public static void main(String [] argv){
    	List<Thread> tList = new ArrayList<>();
        Thread t0 = new Thread(new SynClass3(tList));
        Thread t1 = new Thread(new SynClass3(tList));
        Thread t2 = new Thread(new SynClass3(tList));
        Thread t3 = new Thread(new SynClass3(tList));
        Thread t4 = new Thread(new SynClass3(tList));
        tList.add(t0);
        tList.add(t1);
        tList.add(t2);
        tList.add(t3);
        tList.add(t4);
        t0.start(); // 先启动 第0个
    }
}